home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 9525 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  4.2 KB

  1. Path: news.clark.net!not-for-mail
  2. From: gusty@clark.net (Harlan Messinger)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: C++ OO question (long)
  5. Date: 28 Feb 1996 21:59:11 GMT
  6. Organization: Clark Internet Services, Inc., Ellicott City, MD USA
  7. Message-ID: <4h2j7f$nek@clarknet.clark.net>
  8. References: <4h08uq$mve@madeline.INS.CWRU.Edu>
  9. NNTP-Posting-Host: explorer.clark.net
  10. Mime-Version: 1.0
  11. Content-Type: TEXT/PLAIN; charset=ISO-8859-1
  12. Content-Transfer-Encoding: 8bit
  13. X-Newsreader: TIN [UNIX 1.3 950726BETA PL0]
  14.  
  15. Bryan Murphy (bf461@cleveland.Freenet.Edu) wrote:
  16. : Bellow is the program I wrote.  It implements a class called 
  17. : Matrix, which allocates memory on the heap for the storage of
  18. : a matrix of XxY dimensions.  It also implements a copy constructor
  19. : for assignment, and a couple of different mathematical operations
  20. : to be performed on the matrix.
  21.  
  22. "Implements a copy constructor for assignment": this is the answer to 
  23. problem 1. Copy construction and assignment are separate operations. Even 
  24. though
  25.  
  26.     Matrix M3 = M1 * M2;
  27.  
  28. looks like assignment, it is instead a constructor invocation equivalent to
  29.  
  30.     Matrix M3(M1 * M2);
  31.  
  32. and will use your copy constructor, which apparently works.
  33.  
  34. When instead you have the following:
  35.  
  36.     Matrix M3;
  37.     M3 = M1 * M2;
  38.  
  39. the second line IS an assignment. But you haven't defined an assignment 
  40. operator for your Matrix class. It happens that assignment, along with 
  41. the empty copy constructor and the destructor, is an operation that the 
  42. compiler will define by default if you don't provide a member function 
  43. for it explicitly. But what the default assignment operator does is a 
  44. member-by-member assignment.
  45.  
  46. Let's look at what you're assigning to M3. It's a temporary Matrix that 
  47. is the product of M1 and M2. Let's call it MT. MT has a member called 
  48. MatrixData that points to an array that was dynamically allocated by the 
  49. operator * function. However, only the pointer is a _member_ of MT. The 
  50. matrix elements are in an allocated buffer somewhere out in space.
  51.  
  52. Assigning MT to M3 by default sets M3.xdim = MT.xdim and M3.ydim = 
  53. MT.ydim. No problem there. But then it sets M3.MatrixData = 
  54. MT.MatrixData. In other words, M3 now has a pointer that points to the 
  55. same buffer that MT points to. It hasn't allocated a buffer of its own.
  56.  
  57. Once the assignment is finished, MT, being a temporary, disappears. Since 
  58. you've provided a proper destructor, MT's destructor deletes 
  59. MT.MatrixData, sending it back to the heap. But M3.MatrixData was 
  60. pointing to the same array! Which means that M3.MatrixData is now 
  61. pointing to garbage. And your program blows up.
  62.  
  63. You can either:
  64.  
  65.     1. Rely on the default assignment operator, but instead of
  66.         having MatrixData be a pointer to a dynamically
  67.         allocated block of memory, have it BE (not point to)
  68.         array-type (a.k.a. vector) class whose constructor and 
  69.         destructor take care of allocation and deallocation 
  70.         automatically, and that has its own assignment operator. 
  71.         Have the constructor of Matrix initialize MatrixData.
  72.  
  73.     2. Create your own assignment member function that includes
  74.         the same data allocation feature as the copy constructor.
  75.  
  76.         Matrix &operator =(const Matrix &mat)
  77.         {
  78.             // Assign xdim and ydim.
  79.                 ...
  80.             // Allocate a new buffer
  81.             // to hold the data to be copied from mat.
  82.                 ...
  83.             // Delete the array currently pointed to
  84.             // by MatrixData, and then set MatrixData
  85.             // to point to the new buffer.
  86.                 ...
  87.             return *this; // usual operator = convention.
  88.         }
  89.  
  90. : and I have another question related to this.  When I define
  91. : the Matrix M3 and assign it right away, is the Default Blank
  92. : Constructor called, THEN the Copy Constructor?  Or just the
  93. : copy constructor?  
  94.  
  95. Reviewing from above, the statement of the form
  96.  
  97.     Matrix M3 = M1 * M2;
  98.  
  99. IS a call to the copy constructor. And when a class is constructed, only 
  100. one of its constructors is called.
  101.  
  102. Also, say the copy Constructor was called.
  103. : When the new data is copied over, is the Destructor called 
  104. : before the copy constructor is used to copy the new data over?
  105.  
  106. No, afterwards, but again, the point is that in your latter scenario the
  107. copy constructor ISN'T called because you're assigning, not constructing.
  108. And default assignment wasn't creating a buffer for M3. 
  109.  
  110.